package cn.virens.common.boot.rabbit;

import cn.virens.common.util.exception.APIException;
import com.alibaba.fastjson2.JSON;
import com.rabbitmq.client.AMQP.BasicProperties;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;

import java.io.IOException;

public class RabbitMessage implements AutoCloseable {
    // 判断消息是否已经应答
    private boolean msg_expend_falg = false;

    private final Message message;
    private final Channel channel;

    public RabbitMessage(Message message, Channel channel) {
        this.message = message;
        this.channel = channel;
    }

    /**
     * 获取消息内容(使用JSON转换对象)
     *
     * @param <T>
     * @param clazz 目标类型
     * @return
     * @throws APIException
     */
    public <T> T getBody(Class<T> clazz) throws APIException {
        return JSON.parseObject(getBody(), clazz);
    }

    /**
     * 获取消息内容
     *
     * @return
     * @throws APIException
     */
    public byte[] getBody() throws APIException {
        return message.getBody();
    }

    /**
     * 回复消息-执行应答动作
     *
     * @param properties 消息属性
     * @param massage    消息内容
     * @throws APIException
     */
    public void basicReply(BasicProperties properties, byte[] massage) throws IOException {
        this.channel.basicPublish("", getProperties().getReplyTo(), properties, massage);
    }

    /**
     * 回复消息-消息属性构建
     *
     * @return
     * @throws APIException
     */
    public BasicProperties.Builder basicReplyBuilder() throws APIException {
        BasicProperties.Builder builder = new BasicProperties.Builder();
        builder.correlationId(getProperties().getCorrelationId());
        builder.contentType("application/json");
        builder.contentEncoding("utf-8");

        return builder;
    }

    /**
     * 拒收消息(可多条)
     *
     * @param multiple 是否多条
     * @param requeue  返回队列
     * @throws APIException
     */
    public void basicNack(boolean multiple, boolean requeue) throws IOException {
        this.channel.basicNack(getDeliveryTag(), multiple, requeue);
        this.msg_expend_falg = true;
    }

    /**
     * 拒收消息
     *
     * @param requeue 返回队列
     * @throws APIException
     */
    public void basicReject(boolean requeue) throws IOException {
        this.channel.basicReject(getDeliveryTag(), requeue);
        this.msg_expend_falg = true;
    }

    /**
     * 确认消息
     *
     * @param multiple 是否多条
     * @throws APIException
     */
    public void basicAck(boolean multiple) throws IOException {
        this.channel.basicAck(getDeliveryTag(), multiple);
        this.msg_expend_falg = true;
    }

    /**
     * 获取消息头
     *
     * @param <T>
     * @param headerName 消息头
     * @return
     * @throws APIException
     */
    public <T> T getHeader(String headerName) throws APIException {
        return getProperties().getHeader(headerName);
    }

    /**
     * 获取消息ID
     *
     * @return
     * @throws APIException
     */
    public long getDeliveryTag() throws APIException {
        return getProperties().getDeliveryTag();
    }

    public MessageProperties getProperties() {
        return message.getMessageProperties();
    }

    @Override
    public void close() throws IOException {
        if (!this.msg_expend_falg) {
            this.basicAck(false);
        }
    }
}
